package org.brisling.common.aspect;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.brisling.base.domain.RetDomain;
import org.brisling.base.domain.SimpleResponseObj;
import org.brisling.base.domain.inf.SimpleDomainInf;
import org.brisling.base.service.AbstractBaseService;
import org.brisling.common.SysConfig;
import org.brisling.common.util.LongUtil;
import org.brisling.portal.queryService.QueryPortalService;
import org.brisling.sysman.domain.SysLogs;
import org.brisling.sysman.domain.Users;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 
 * <p>Title: AspectService</p>
 * <p>Description: 切面服务</p>
 * <p>Company: tongking</p>
 * @author jackson wang
 * @since 1.0
 * @version 1.0
 * @date 2017年4月22日 下午7:12:57
 */
@Component
@Aspect
public class AspectService   {

	private  static  final Logger logger = LoggerFactory.getLogger(AspectService. class); 
	
	@Autowired
	private QueryPortalService portalService;	
	
	
	private final String login_point_cut = "execution(* org.brisling.authorize.shiro.ShiroSecurityService.*Login(..))";
	
	private  final String save_point_cut = "execution(* org.brisling..service.*.save*(..))";
	
	private  final String del_point_cut = "execution(* org.brisling..service.*.delRow(..))";
	
	//Controller层切点  
	/* (non-Javadoc)
	 * @see org.brisling.common.aspect.AspectServiceInf#controllerAspect()
	 */
	@Pointcut(save_point_cut)  
	public  void controllerAspect() {  
	} 	
	
	
	
	/* (non-Javadoc)
	 * @see org.brisling.common.aspect.AspectServiceInf#doBefore(org.aspectj.lang.JoinPoint)
	 */ 
    @Before("controllerAspect()")
    public void doBefore(JoinPoint joinPoint) {
        
    }    
    
//    //配置controller环绕通知,使用在方法aspect()上注册的切入点
//      @Around("controllerAspect()")
//      public void around(JoinPoint joinPoint){
//          System.out.println("==========开始执行controller环绕通知===============");
//          long start = System.currentTimeMillis();
//          try {
//              ((ProceedingJoinPoint) joinPoint).proceed();
//              long end = System.currentTimeMillis();
//              if(logger.isInfoEnabled()){
//                  logger.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms!");
//              }
//              System.out.println("==========结束执行controller环绕通知===============");
//          } catch (Throwable e) {
//              long end = System.currentTimeMillis();
//              if(logger.isInfoEnabled()){
//                  logger.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms with exception : " + e.getMessage());
//              }
//          }
//      }
    
    /* (non-Javadoc)
	 * @see org.brisling.common.aspect.AspectServiceInf#after(org.aspectj.lang.JoinPoint)
	 */  
    @AfterReturning(pointcut=save_point_cut,returning="returnValue")
    public void saveAfterReturn(JoinPoint joinPoint,Object returnValue){
    
  
         
       logger.debug("=====controller后置通知开始====="); 
       if(SysConfig.getEnableLog()){
    	   HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();  
           
      
       SysLogs log = new SysLogs();
        String targetName = null;
        String methodName = null;
         try {  
        	Object obj = joinPoint.getTarget() ;
         	if(obj!=null && (obj instanceof AbstractBaseService)){
         		AbstractBaseService as = (AbstractBaseService)obj;
         		log.setBizcode(as.getModuleName());
         	}
            targetName = joinPoint.getTarget().getClass().getName();  
            methodName = joinPoint.getSignature().getName();  
            Object[] arguments = joinPoint.getArgs();           
            if(arguments!=null && arguments[0]!=null){
            	log.setJsonData(arguments[0].toString());
            }
        }  catch (Exception e) {  
            //记录本地异常日志  
            logger.error("==后置通知异常==");  
            logger.error("异常信息:{}", e.getMessage());  
        }  
         
       //*========数据库日志=========*//  
           
         
         if(checkExclude(targetName) ){
        	 
        	 //确保不记录log事件
	         log.setEventName((targetName + "." + methodName + "()"));  
	         
	         //日志类型：日志类型,：1、登录；2、保存；3、删除；4、异常
	         log.setLogType(2);  
	         log.setLogTypeName("保存");
	         log = checkReturnVal(returnValue,log);	         
	         
	         //保存数据库  
	         this.logRecord(request, log); 
         }
       }
         logger.debug("=====controller后置通知结束=====");  
    } 
    
    @AfterReturning(pointcut=del_point_cut,returning="returnValue")
    /**
     * 删除操作日志
     * @param joinPoint
     * @param returnValue
     */
    public void delAfterReturn(JoinPoint joinPoint,Object returnValue){
    
    	logger.debug("=====controller后置通知开始====="); 
    	if(SysConfig.getEnableLog()){
       HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();  
         
       
       SysLogs log = new SysLogs();  
        String targetName = null;
        String methodName = null;
         try {  
            
        	 Object obj = joinPoint.getTarget() ;
        	if(obj!=null && (obj instanceof AbstractBaseService)){
        		AbstractBaseService as = (AbstractBaseService)obj;
        		log.setBizcode(as.getModuleName());
        	}
            targetName = joinPoint.getTarget().getClass().getName();  
            methodName = joinPoint.getSignature().getName();  
            Object[] arguments = joinPoint.getArgs();           
            if(arguments!=null){
            	if(arguments!=null && arguments[0]!=null){
            		log.setJsonData(String.format("{\"id\":\"%1$s\"}", arguments[0].toString()));
            	}
            }
        }  catch (Exception e) {  
            //记录本地异常日志  
            logger.error("==后置通知异常==");  
            logger.error("异常信息:{}", e.getMessage());  
        }  
         
       //*========数据库日志=========*//  
         
         
         if(checkExclude(targetName) ){
        	 
        	 //确保不记录log事件
	         log.setEventName((targetName + "." + methodName + "()"));  
	         
	         //日志类型：日志类型,：1、登录；2、保存；3、删除；4、异常
	         log.setLogType(3);  
	         log.setLogTypeName("删除");         
	         
	         log = checkReturnVal(returnValue,log);	             
	         
	         //保存数据库  
	         this.logRecord(request, log); 
         }
    	}
         logger.debug("=====controller后置通知结束=====");  
    } 
    
    
    //配置后置返回通知,使用在方法aspect()上注册的切入点
      /* (non-Javadoc)
	 * @see org.brisling.common.aspect.AspectServiceInf#afterReturn(org.aspectj.lang.JoinPoint)
	 */
    @AfterReturning(pointcut=login_point_cut,returning="returnValue")
      public void loginAfterReturn(JoinPoint joinPoint,Object returnValue){
    	
    	if(SysConfig.getEnableLog()){
    	HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();  
        
        
    	logger.debug("=====controller后置通知开始=====");
        String targetName = null;
        String methodName = null;
         try {  
            
            targetName = joinPoint.getTarget().getClass().getName();  
            methodName = joinPoint.getSignature().getName();  
            Object[] arguments = joinPoint.getArgs();
        }  catch (Exception e) {  
            //记录本地异常日志  
            logger.error("==后置通知异常==");  
            logger.error("异常信息:{}", e.getMessage());  
        }  
         
       //*========数据库日志=========*//  
         SysLogs log = new SysLogs();  
         
         if(checkExclude(targetName) ){
        	 
        	 //确保不记录log事件
	         log.setEventName((targetName + "." + methodName + "()"));  
	         
	         
	         //日志类型：1、登录；2、保存；3、删除；4、异常
	         log.setLogType(1); 
	         log.setLogTypeName("登录");
	         
	         //判断返回类型
	         if(returnValue instanceof SimpleResponseObj){
		         SimpleResponseObj ret = (SimpleResponseObj)returnValue;
		         //登录执行状态
		         if(ret!=null && ret.getRetStatus().compareTo("success")==0){
		        	 log.setOperateStatus(1);
		        	 log.setOperateStatusName("成功");
		        	 
		        	 Users usr = (Users)ret.getRetData();
		        	 log.setUserName(usr.getName());
		         }else{
		        	 log.setOperateStatus(2);
		        	 log.setOperateStatusName("失败");
		         }
		         
		         log.setUserId(LongUtil.getLongValue(ret.getUserid(), null));
	         }
	         this.logRecord(request, log);
	           
         }
    	}
         logger.debug("=====controller后置通知结束=====");  
      }

	
    private void logRecord(HttpServletRequest request,SysLogs log){
    	
    	//读取session中的用户  
        String userid = request.getRemoteUser();
        
        if(userid!=null){
        	Users user = SysConfig.getUsr(userid);
        	
        	if(user!=null){
	        	log.setUserId(user.getId());
	        	log.setUserName(user.getName());
        	}
        }
         
        //请求的IP  
        String ip = request.getRemoteAddr();
        
        String mac = request.getRemoteHost();
    	
        logger.debug("请求人:" + log.getUserName());  
        logger.debug("请求IP:" + ip); 
        
        log.setIp(ip);
        log.setMac(mac);
        log.setExceptionCode( null);  
        log.setExceptionDetail( null);  
        log.setEventRecord( null);  
        log.setCreater(log.getUserId());  
        
        log.setCreateTime(new Date());  
        
      //保存数据库  
        portalService.logRecord(log);
    }
    
    /**
     * 检查返回值
     * @param returnValue
     * @param log
     * @return
     */
    private SysLogs checkReturnVal(Object returnValue,SysLogs log){
    	
    	boolean ischecked = false;
    	String status = "error";
    	String suc_status = "success";
    	if(returnValue instanceof RetDomain ){
    		RetDomain ret = (RetDomain)returnValue;
    		status = ret.getStatus();
    		ischecked = true;
        }
    	
    	if(!ischecked && (returnValue instanceof SimpleDomainInf)){
	         SimpleDomainInf ret = (SimpleDomainInf)returnValue;
	         if(ret!=null && ret.getId()!=null){
	        	 status = suc_status;
	     		 ischecked = true;
	         }  
        }
        	
       	if(!ischecked ){
       		if(returnValue!=null){       	
	       		status = suc_status;
	       	}
       	}
        
       	if(status!=null && status.compareTo("success")==0){
       	 log.setOperateStatus(1);
	         log.setOperateStatusName("成功");
        }else{
       	 log.setOperateStatus(2);
	         log.setOperateStatusName("失败");
        }	   
    	
    	return log;
    }
    
    /**
     * 检查是否日志排除服务
     * @param targetName
     * @return
     */
    private boolean checkExclude(String targetName){
    	
    	if(targetName!=null && 
    			(targetName.indexOf("LogService")<0) && //日志服务
    			(targetName.indexOf("ScheduledService")<0) &&	//计划任务
    			(targetName.indexOf("LogDetailService")<0)){	//日志明细
    		return true;
    	}
    	
    	return false;
    		
    }
	
}
